package com.dd.cloud.user.service.menu.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dd.cloud.common.constants.ClientMenuConstants;
import com.dd.cloud.user.entity.menu.ClientMenu;
import com.dd.cloud.user.entity.menu.ClientMenuUser;
import com.dd.cloud.common.interceptor.UserInterceptor;
import com.dd.cloud.user.mapper.menu.ClientMenuMapper;
import com.dd.cloud.user.req.menu.ClientMenuPageReq;
import com.dd.cloud.user.req.menu.CreatClientMenuReq;
import com.dd.cloud.user.req.menu.UpdateClientMenuReq;
import com.dd.cloud.user.res.menu.ClientMenuPageRes;
import com.dd.cloud.user.service.menu.IClientMenuService;
import com.dd.cloud.user.service.menu.IClientMenuUserService;
import com.dd.cloud.common.vo.LoginInfo;
import com.dd.cloud.common.enums.ZkExceptionEnum;
import com.dd.cloud.common.exception.ZekeException;
import com.dd.cloud.common.utils.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;

/**
 * <p>
 * 客户端菜单表 服务实现类
 * </p>
 *
 * @author czg
 * @since 2022-05-07
 */
@Service
public class ClientMenuServiceImpl extends ServiceImpl<ClientMenuMapper, ClientMenu> implements IClientMenuService {

    @Autowired
    private IClientMenuUserService clientMenuUserService;

    /**
     * 添加统一的菜单内容
     * @param req
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addWholeClientMenu(CreatClientMenuReq req) {
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo(LoginInfo.UserType.ADMIN).get();
        QueryWrapper<ClientMenu> qw = new QueryWrapper<>();
        qw.lambda().eq(ClientMenu::getTitle, req.getTitle())
                .ne(ClientMenu::getStatus, ClientMenuConstants.Status.DELETE);
        ClientMenu clientMenu = getOne(qw);
        if (clientMenu != null) {
            throw new ZekeException(400, "菜单标题已存在");
        }
        //设置有排序, 就需要重排序
        if (req.getSort() != null){
            qw = new QueryWrapper<>();
            qw.lambda().eq(ClientMenu::getClient, req.getClient())
                    .eq(ClientMenu::getSort, req.getSort())
                    .ne(ClientMenu::getStatus, ClientMenuConstants.Status.DELETE);
            clientMenu = getOne(qw);
            if (clientMenu != null){
                //当前设置的排序位置已存在, 那已有的排序都需要往后移位1
                UpdateWrapper<ClientMenu> uw = new UpdateWrapper<>();
                uw.lambda().setSql("sort = sort + 1")
                        .eq(ClientMenu::getClient, req.getClient())
                        .ge(ClientMenu::getSort, req.getSort())
                        .ne(ClientMenu::getStatus, ClientMenuConstants.Status.DELETE);
                update(uw);
            }
        }

        clientMenu = new ClientMenu();
        BeanUtils.copyProperties(req, clientMenu);
        if (req.getSort() == null){
            //未设置重排序, 就排在最后一个, 查询最大的排序
            qw = new QueryWrapper<>();
            qw.lambda().eq(ClientMenu::getClient, req.getClient())
                    .select(ClientMenu::getSort)
                    .ne(ClientMenu::getStatus, ClientMenuConstants.Status.DELETE)
                    .orderByDesc(ClientMenu::getSort).last("limit 1");
            clientMenu = getOne(qw);
            int sort = 1;
            if (clientMenu != null && clientMenu.getSort() != null){
                sort = clientMenu.getSort();
            }
            clientMenu.setSort(sort);
        }

        clientMenu.setCreateDate(LocalDateTime.now());
        clientMenu.setOperId(loginInfo.getId());
        int i = getBaseMapper().insert(clientMenu);
        if (i <= 0) {
            throw new ZekeException(ZkExceptionEnum.ADD_ERROR);
        }
        //添加默认显示的菜单
        ClientMenuUser menuUser = new ClientMenuUser();
        menuUser.setClientId(clientMenu.getId());
        menuUser.setUserId(ClientMenuConstants.Whole.TYPE);
        menuUser.setUserType(ClientMenuConstants.Whole.TYPE);
        menuUser.setCreateDate(LocalDateTime.now());
        menuUser.setStatus(ClientMenuConstants.Status.NORMAL);
        boolean flag = clientMenuUserService.save(menuUser);
        if (!flag){
            throw new ZekeException(ZkExceptionEnum.ADD_ERROR);
        }
    }

    /**
     * 修改统一菜单内容
     * @param req
     */
    @Override
    public void updateWholeClientMenu(UpdateClientMenuReq req) {
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo(LoginInfo.UserType.ADMIN).get();
        ClientMenu clientMenu = getById(req.getId());
        if (clientMenu == null){
            throw new ZekeException(400, "菜单不存在");
        }

        QueryWrapper<ClientMenu> qw = new QueryWrapper<>();
        if (!clientMenu.getTitle().equals(req.getTitle())){
            qw.lambda().eq(ClientMenu::getTitle, req.getTitle())
                    .ne(ClientMenu::getStatus, ClientMenuConstants.Status.DELETE);
            clientMenu = getOne(qw);
            if (clientMenu != null) {
                throw new ZekeException(400, "菜单标题已存在");
            }
        }

        //设置有新的排序, 就需要重排序
        if (req.getSort() != null && !req.getSort().equals(clientMenu.getSort())){
            qw = new QueryWrapper<>();
            qw.lambda().eq(ClientMenu::getClient, req.getClient())
                    .eq(ClientMenu::getSort, req.getSort())
                    .ne(ClientMenu::getStatus, ClientMenuConstants.Status.DELETE);
            clientMenu = getOne(qw);
            if (clientMenu != null){
                //当前设置的排序位置已存在, 那已有的排序都需要往后移位1
                UpdateWrapper<ClientMenu> uw = new UpdateWrapper<>();
                uw.lambda().setSql("sort = sort + 1")
                        .eq(ClientMenu::getClient, req.getClient())
                        .ge(ClientMenu::getSort, req.getSort())
                        .ne(ClientMenu::getStatus, ClientMenuConstants.Status.DELETE);
                update(uw);
            }
        }

        clientMenu = new ClientMenu();
        BeanUtils.copyProperties(req, clientMenu);
        if (req.getSort() == null){
            //未设置重排序, 就排在最后一个, 查询最大的排序
            qw = new QueryWrapper<>();
            qw.lambda().eq(ClientMenu::getClient, req.getClient())
                    .ne(ClientMenu::getStatus, ClientMenuConstants.Status.DELETE)
                    .orderByDesc(ClientMenu::getSort).last("limit 1");
            ClientMenu clientMenu2 = getOne(qw);
            int sort = 1;
            if (clientMenu2 != null && clientMenu2.getSort() != null){
                sort = clientMenu2.getSort();
            }
            clientMenu.setSort(sort);
        }
        clientMenu.setCreateDate(LocalDateTime.now());
        clientMenu.setOperId(loginInfo.getId());
        boolean flag = updateById(clientMenu);
        if (!flag){
            throw new ZekeException(ZkExceptionEnum.UPDATE_ERROR);
        }
    }

    /**
     * 修改菜单状态
     * @param id
     * @param status
     */
    @Override
    public void updateWholeClientMenuStatus(Integer id, Integer status) {
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo(LoginInfo.UserType.ADMIN).get();
        ClientMenu clientMenu = getById(id);
        if (clientMenu == null){
            throw new ZekeException(400, "菜单不存在");
        }
        if (!ObjectUtils.refrect(ClientMenuConstants.Status.class, status)){
            throw new ZekeException(ZkExceptionEnum.STATUS_DATA_ERROR);
        }
        if (status.equals(clientMenu.getStatus())){
            return;
        }
        clientMenu.setStatus(status);
        boolean flag = updateById(clientMenu);
        if (!flag){
            throw new ZekeException(ZkExceptionEnum.UPDATE_ERROR);
        }
    }

    /**
     * 分页查询菜单
     * @param req
     * @return
     */
    @Override
    public Page<ClientMenuPageRes> getClientMenuPage(ClientMenuPageReq req) {
        if (!StringUtils.isBlank(req.getStatus())){
            req.setStatusStr(req.getStatus().split(","));
        }
        Page<ClientMenuPageRes> page = req.pagePojo();
        page = getBaseMapper().getClientMenuPage(page, req);
        return page;
    }
}
